<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
<meta charset="utf-8">
<title></title>
  <link href="http://www.yanhuangxueyuan.com/markdown.css" rel="stylesheet" type="text/css">
  </head>
  <body>
<h1 id="-uniform">着色器——uniform</h1>
<p>使用着色器语言GLSL编写着色器代码的时候，都会使用关键字<code>attribute</code>和<code>uniform</code>来声明一些变量，通常关键字<code>attribute</code>用来声明一些几何体顶点数据，例如顶点位置数据、顶点法向量数据....，<code>uniform</code>关键字通常用来声明模型矩阵、光源颜色、光源位置等变量。</p>
<ul>
<li><code>attribute</code>：属性</li>
<li><code>uniform</code>：统一</li>
</ul>
<p>Three.js渲染器渲染场景的时候，几何体的顶点位置、颜色、法向量等数据，系统会自动传递给着色器中<code>attribute</code>关键字声明的对应顶点变量。</p>
<p>着色器中<code>uniform</code>关键字声明的模型矩阵<code>modelMatrix</code>、视图矩阵<code>viewMatrix</code>、投影矩阵<code>projectionMatrix</code>等Three.js系统定义的uniform变量，Threejs系统会自动从对应的Threejs对象中解析数据并自动传递。比如视图矩阵的值Three.js系统会从相机对象中获得具体的值，然后传递给<code>viewMatrix</code>变量。</p>
<h3 id="-uniform-">自定义<code>uniform</code>变量数据传递</h3>
<p>如果程序员在着色器中任意命名自定义了一个uniform变量,如果需要给该uniform变量传递数据，在原生WebGL中需要特定的WebGL API来传递数据，在Three.js中不需要这样，只需要在着色器材质对象的<code>ShaderMaterial</code>的属性<code>.uniforms</code>中定义一个属性，属性名字和着色器中uniform变量保持一致，对于程序员而言只需要保持名字一致，至于数据传递过程，Three.js系统会自动帮你完成。</p>
<h2 id="-uniforms-">属性<code>.uniforms</code>使用案例</h2>
<p>片元着色器中通过uniform关键字声明了一个颜色变量color，为了给该变量传递数据在ShaderMaterial对象的uniforms属性中定义了一个名为color的属性，按照Three.js系统uniform变量数据自动传递的机制，如果你在着色器代码中自定义声明了多个uniform变量，只要名字和ShaderMaterial对象中uniform数据的名字保持一直就可以正确完成数据传递。</p>
<pre><code class="lang-JavaScript"><span class="hljs-comment">&lt;!-- 片元着色器 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"fragmentShader"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"x-shader/x-fragment"</span>&gt;</span><span class="javascript">
  <span class="hljs-comment">// color变量数据来自ShaderMaterial的uniforms属性的color属性</span>
  uniform vec3 color;
  <span class="hljs-keyword">void</span> main() {
 <span class="hljs-comment">// gl_FragColor = vec4(1.0,0.0,0.0,1.0);</span>
 gl_FragColor = vec4(color,<span class="hljs-number">1.0</span>);
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>ShaderMaterial的uniforms属性代码</p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">var</span> material = <span class="hljs-keyword">new</span> THREE.ShaderMaterial({
  <span class="hljs-comment">//定义uniforms属性，uniforms的属性和着色器中的uniform变量相对应</span>
  uniforms:{
<span class="hljs-comment">// 颜色属性clor对应片元着色器代码中uniform声明的color变量</span>
color:{value:<span class="hljs-keyword">new</span> THREE.Color(<span class="hljs-number">0xff0000</span>)}
  },
  <span class="hljs-comment">// 顶点着色器</span>
  vertexShader: <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'vertexShader'</span>).textContent,
  <span class="hljs-comment">// 片元着色器</span>
  fragmentShader: <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'fragmentShader'</span>).textContent,
});
</code></pre>
<h3 id="-">数据类型</h3>
<p>着色器声明的uniform变量数据类型要和着色器材质对象的<code>ShaderMaterial</code>的属性<code>.uniforms</code>的属性的属性值数据类型保持一致。例如<code>value:new THREE.Color(0xff0000)</code>对应的着色器中数据类型是<code>vec3</code>,<code>value:new THREE.Matrix4()</code>对应的着色器中数据类型是<code>mat4</code>。</p>
<p><code>value</code>的值和和着色器数据类型的对应关系可以参考Threejs文档core分类下的<a href="http://www.yanhuangxueyuan.com/threejs/docs/index.html#api/core/Uniform">Uniform</a></p>

<div class="">
  <a href="http://www.yanhuangxueyuan.com/">作者技术博客</a>
</div>
  </body>
</html>
